//
//  UIList.cpp
//  storm
//
//  Created by wangdi on 13-8-18.
//
//

#include "UIList.h"
#include "UIListItem.h"
using namespace cocos2d;

namespace storm
{
    /////////////////////////////////////////////////////////////////////////////
    
    void UIList::visit()
    {   
        UpdateList();
        UIPanel::visit();
        
    }
    
    //--------------------------------------------------------------------------------------------------------------/
    bool UIList::isContainsTouch(cocos2d::CCTouch *pTouch)
    {
        return (cocos2d::CCRect(-this->getContentSize().width*this->getAnchorPoint().x,
                                -this->getContentSize().height*this->getAnchorPoint().y,
                                this->getContentSize().width,
                                this->getContentSize().height).containsPoint(this->convertTouchToNodeSpaceAR(pTouch)));
    }
    
    //---------------------------------------------------------------------------------------------------------------/
    void UIList::ItemTouchBegin(cocos2d::CCTouch *pTouch)
    {
        m_bAutoMoving = false;
        m_bTouchMoving = true;
        
        m_ptLast = convertTouchToNodeSpace(pTouch);
        if(m_type == LIST_FROMTOP || m_type == LIST_FROMBOTTOM)
        {
            m_startTouchPos = m_ptLast.y;
        }
        else
        {
            m_startTouchPos = m_ptLast.x;
        }
    }
    
    //---------------------------------------------------------------------------------------------------------------/
    void UIList::ItemTouchMove(cocos2d::CCTouch *pTouch)
    {
        CCPoint ptCur = convertTouchToNodeSpace(pTouch);
        if(m_type == LIST_FROMTOP || m_type == LIST_FROMBOTTOM)
        {
            if(fabsf(m_startTouchPos - ptCur.y) > 5)
            {
                m_startTouchPos = ptCur.y;
            }
        }
        else
        {
            if(fabsf(m_startTouchPos - ptCur.x) > 5)
            {
                m_startTouchPos = ptCur.x;
            }
        }
        
        float diff;
        if (m_type == LIST_FROMLEFT || m_type == LIST_FROMRIGHT)
        {
            diff =ptCur.x- m_ptLast.x;
            
            if(getContentSize().width > m_itemSizeCount)
            {
                diff *= 0.5f;
            }
            else if((m_startPos > 0 && diff > 0) ||
                    (m_startPos + m_itemSizeCount <getContentSize().width && diff < 0))
            {
                diff *= 0.5f;
            }
            
        }
        else
        {
            diff = ptCur.y - m_ptLast.y ;
            
            if(getContentSize().height > m_itemSizeCount)
            {
                diff *= 0.5f;
            }
            else if((m_startPos - m_itemSizeCount > 0 && diff > 0) ||
                    (m_startPos < getContentSize().height && diff < 0))
            {
                diff *= 0.5f;
            }
            
            
        }
        
        m_curSpeed = diff * m_scale;
        m_bTouchMoving = true;
        //m_startPos = diff;
        m_ptLast = ptCur;
        m_startPos += m_curSpeed;
        ResortItems();
    }
    
    //-------------------------------------------------------------------------------------------------------------/
    void UIList::ItemTouchEnd(CCTouch *pTouch)
    {
        m_bTouchMoving = false;
    }
    
  
    //--------------------------------------------------------------------------------------------------------------/
    UIList *UIList::Create(cocos2d::CCSize s, ListType type)
    {
        UIList *pList = UIList::create();
        pList->InitState(type, s);
        return pList;
    }
    
    UIList::UIList()
        : m_pActiveItem(NULL)
        , m_bTouchMoving(false)
        , m_itemSizeCount(0)
        , m_parentScale(1.0f)
        , m_bStopUpdate(false)
    {
        
    }
    //--------------------------------------------------------------------------------------------------------------/
    void UIList::InitState(ListType type, cocos2d::CCSize s)
    {
        m_scale = CCDirector::sharedDirector()->getWinSize().width / CCDirector::sharedDirector()->getWinSizeInPixels().width ;

        m_type = type;
        m_rcClip.origin = CCPointZero;
        m_rcClip.size   = s;
        
        setContentSize(CCSize(s.width * m_scale, s.height * m_scale));
        
        if(!s.equals(CCSizeZero))
        {
            if(type == LIST_FROMTOP)
            {
                setAnchorPoint(ccp(0.5, 1));
                m_startPos = getContentSize().height * getAnchorPoint().y;
            }
            else if(type == LIST_FROMBOTTOM)
            {
                setAnchorPoint(ccp(0.5, 0));
                m_startPos = getContentSize().height * getAnchorPoint().y;
            }
            else if(type == LIST_FROMLEFT)
            {
                setAnchorPoint(ccp(0, 0.5));
                m_startPos = 0;
            }
            else if(type == LIST_FROMRIGHT)
            {
                setAnchorPoint(ccp(1, 0.5));
                m_startPos = getContentSize().width * getAnchorPoint().x;
            }
        }
        
        m_rcClip.origin.x = - m_rcClip.size.width * getAnchorPoint().x;
        m_rcClip.origin.y = - m_rcClip.size.height * getAnchorPoint().y;
        
        ignoreAnchorPointForPosition(false);
        m_bAutoMoving = false;
        m_curSpeed = 0;
    }
    
    //---------------------------------------------------------------------------------------------------------------/
    void UIList::SetParentScale(float scale)
    {
        m_parentScale = scale;
    }
    
    //----------------------------------------------------------------------------------------------------------------/
    void UIList::AddItem(UIListItem *pNewItem)
    {
        pNewItem->SetParentList(this);
        m_listItems.push_back(pNewItem);
        m_listWidgets.push_back(pNewItem);
        m_itemSizeCount += pNewItem->GetSize();
        addChild(pNewItem);
        ResortItems();
    }
    
    //----------------------------------------------------------------------------------------------------------------/
    void UIList::InsertItem(UIListItem *pNewItem, int pos)
    {
        pNewItem->SetParentList(this);
        m_listItems.insert(m_listItems.begin(), pNewItem);
        m_listWidgets.push_back(pNewItem);
        m_itemSizeCount += pNewItem->GetSize();
        addChild(pNewItem);
        ResortItems();
    }
    //-----------------------------------------------------------------------------------------------------------/
    void UIList::RemoveItem(UIListItem *pItem)
    {
        if(NULL == pItem)
        {
            return;
        }
        std::list<UIListItem *>::iterator iter = m_listItems.begin();
        UIListItem *pItemToRemove;
        for(; iter != m_listItems.end(); iter++)
        {
            if(*iter == pItem)
            {
                pItemToRemove = pItem;
                break;
            }
        }
        
        if(iter == m_listItems.end())
        {
            // 末尾
            return;
        }
        
        iter++;
        if(iter != m_listItems.end())
        {
            float xDiff = 0;
            float yDiff = 0;
            if(m_type == LIST_FROMLEFT)
            {
                xDiff = (*iter)->getPosition().x - pItem->getPosition().x;
            }
            else if(m_type == LIST_FROMTOP)
            {
                yDiff = (*iter)->getPosition().y - pItem->getPosition().y;
            }
            for(; iter != m_listItems.end(); iter++)
            {
                (*iter)->runAction(CCSequence::createWithTwoActions(CCMoveBy::create(0.2f, ccp(-xDiff, -yDiff)), CCCallFunc::create(this, callfunc_selector(UIList::OnRemoveItem))));
            }
            
            m_bStopUpdate = true;
        }
        
        m_itemSizeCount -= pItem->GetSize();
        m_listWidgets.remove(pItem);
        m_listItems.remove(pItem);
        pItem->removeFromParentAndCleanup(true);
        
    }
    
    //-------------------------------------------------------------------------------------------------------------/
    void UIList::OnRemoveItem()
    {
        m_bStopUpdate = false;
    }
    
    //-------------------------------------------------------------------------------------------------------------/
    UIListItem *UIList::ItemByIndex(int index)
    {
        if(index >= m_listItems.size())
        {
            return NULL;
        }
        std::list<UIListItem *>::iterator iter = m_listItems.begin();
        for(int i=0; i<index; i++)
        {
            iter++;
        }
        
        return *iter;
    }
    
    //------------------------------------------------------------------------------------------------------------/
    UIListItem *UIList::ItemByTag(int tag)
    {
        for(std::list<UIListItem *>::iterator iter = m_listItems.begin(); iter != m_listItems.end(); iter++)
        {
            if((*iter)->getTag() == tag)
            {
                return *iter;
            }
        }
        return NULL;
    }
    
    //-------------------------------------------------------------------------------------------------------------/
    int UIList::IndexByTag(int tag)
    {
        int index = 0;
        for(std::list<UIListItem *>::iterator iter = m_listItems.begin(); iter != m_listItems.end(); iter++, index++)
        {
            if((*iter)->getTag() == tag)
            {
                return index;
            }
        }
        
        return -1;
    }
    
    //-------------------------------------------------------------------------------------------------------------/
    void UIList::UpdateList()
    {
        if(m_bStopUpdate || !m_bEnable)
        {
            return;
        }
        float boxSize;
        float distToTop;
        float minPos;
        float maxPos;
        
        if(m_type == LIST_FROMTOP || m_type == LIST_FROMBOTTOM)
        {
            boxSize = getContentSize().height;
            distToTop = boxSize - m_startPos;
            maxPos = m_itemSizeCount;
            minPos = boxSize;
        }
        else
        {
            boxSize = getContentSize().width;
            distToTop = -m_startPos;
            minPos = boxSize - m_itemSizeCount;
            maxPos = 0;
        }
        
        if(!m_bTouchMoving)
        {
            if(m_bAutoMoving)
            {
                if(boxSize > m_itemSizeCount)
                {
                    // ITEM尺寸很小
                    if(fabsf(distToTop) < fabsf(m_curSpeed))
                    {
                        m_bAutoMoving = false;
                        m_startPos += distToTop;
                        m_curSpeed = 0;
                    }
                }
                else
                {
                    if(fabsf(m_startPos - minPos) < fabsf(m_curSpeed))
                    {
                        m_startPos = minPos;
                        m_bAutoMoving = false;
                        m_curSpeed    = 0;
                    }
                    else if(fabsf(m_startPos - maxPos) < fabsf(m_curSpeed))
                    {
                        m_startPos = maxPos;
                        m_bAutoMoving = false;
                        m_curSpeed    = 0;
                    }
                }
            }
            else
            {
                // 自动回滚
                if(m_curSpeed > 0)
                {
                    m_curSpeed -= 1;
                }
                else if(m_curSpeed < 0)
                {
                    m_curSpeed += 1;
                }
                
                if(abs(m_curSpeed) < 1)
                {
                    m_curSpeed = 0;
                }
                
                if(boxSize > m_itemSizeCount)
                {
                    // ITEM尺寸很小
                    m_curSpeed = distToTop / 30.0f;
                    m_bAutoMoving = true;
                }
                else
                {
                    // 有多余未显示的ITEM
                    // 考虑两边超出部分。
                    
                    if(m_startPos > maxPos)
                    {
                        m_curSpeed = (maxPos  - m_startPos) / 30.0f;
                        m_bAutoMoving = true;
                    }
                    else if(m_startPos < minPos)
                    {
                        m_curSpeed = (minPos - m_startPos) / 30.0f;
                        m_bAutoMoving = true;
                    }
                }
            }
            
            m_startPos += m_curSpeed;
            ResortItems();
        }
    }
    
    //------------------------------------------------------------------------------------------------------------------------------------/
    void UIList::ResortItems()
    {
        float startPos = m_startPos;
        float lastSize = 0;
        float maxPos;
        float minPos = 0;
        float s= 1;
        
        if(m_type == LIST_FROMLEFT)
        {
            maxPos = getContentSize().width;
        }
        else if(m_type == LIST_FROMTOP)
        {
            maxPos = getContentSize().height;
            s = -1;
        }
        
        for(std::list<UIListItem *>::iterator iter = m_listItems.begin(); iter != m_listItems.end(); iter++)
        {
            UIListItem *pItem = *iter;
            startPos += ((pItem->GetSize() + lastSize)*0.5f )*s;
            if(m_type == LIST_FROMTOP)
            {
                pItem->setPosition(ccp(m_rcClip.size.width * 0.5f * m_scale, startPos));
            }
            else
            {
                pItem->setPosition(ccp(startPos, m_rcClip.size.height * 0.5f * m_scale));
            }
            
            lastSize = pItem->GetSize();
            
            if(startPos > maxPos || startPos < minPos)
            {
                pItem->setEnable(false);
            }
            else
            {
                pItem->setEnable(true);
            }
        }
    }
}